//
//  ZLColorView.m
//  ZLColorWall
//
//  Created by 赵振磊 on 2024/3/16.
//

#import "ZLColorView.h"

@interface ZLColorView()
/// 底色
@property (nonatomic, strong) CAGradientLayer *bgLayer;
/// 顶色
@property (nonatomic, strong) CAGradientLayer *topLayer;
/// 选中背景色背景
@property (nonatomic, strong) UIView *selBgView;
/// 选中背景色
@property (nonatomic, strong) UIView *selTopView;
/// 色板
@property (nonatomic, strong) UIImage *colorImage;
@end

@implementation ZLColorView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.frame = frame;
        [self.layer addSublayer:self.bgLayer];
        [self.layer addSublayer:self.topLayer];
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0);
        [self.layer renderInContext:UIGraphicsGetCurrentContext()];
        self.colorImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        [self addSubview:self.selBgView];
        UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
        [self addGestureRecognizer:pan];
    }
    return self;
}

- (void)didMoveToSuperview {
    [super didMoveToSuperview];
    self.bgLayer.cornerRadius = self.cornerRadius;
    self.topLayer.cornerRadius = self.cornerRadius;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    UITouch *touch = touches.anyObject;
    CGPoint point = [touch locationInView:self];
    self.selBgView.center = point;
    [self updateSelColor];
}

#pragma mark - action

- (void)panAction:(UIPanGestureRecognizer *)gesture {
    CGPoint newCenter = [gesture locationInView:self];
    newCenter.x = MAX(1, MIN(self.frame.size.width - 1, newCenter.x));
    newCenter.y = MAX(1, MIN(self.frame.size.height, newCenter.y));
    self.selBgView.center = newCenter;
    [gesture setTranslation:CGPointZero inView:self];
    [self updateSelColor];
}

- (void)updateSelColor {
    CGPoint point = self.selBgView.center;
    NSUInteger width = self.colorImage.size.width;
    NSUInteger height = self.colorImage.size.height;
    NSInteger pointX = trunc(point.x);
    NSInteger pointY = trunc(point.y);
    CGImageRef cgImage = self.colorImage.CGImage;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    int bytesPerPixel = 4;
    int bytesPerRow = bytesPerPixel * 1;
    NSUInteger bitsPerComponent = 8;
    unsigned char pixelData[4] = { 0, 0, 0, 0 };
    CGContextRef context = CGBitmapContextCreate(pixelData,
                                                 1,
                                                 1,
                                                 bitsPerComponent,
                                                 bytesPerRow,
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);
    CGContextSetBlendMode(context, kCGBlendModeCopy);
    CGContextTranslateCTM(context, -pointX, pointY-(CGFloat)height);
    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage);
    CGContextRelease(context);
    CGFloat red   = (CGFloat)pixelData[0] / 255.0f;
    CGFloat green = (CGFloat)pixelData[1] / 255.0f;
    CGFloat blue  = (CGFloat)pixelData[2] / 255.0f;
    CGFloat alpha = (CGFloat)pixelData[3] / 255.0f;
    self.selTopView.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
    if (self.colorChange) {
        self.colorChange(self.selTopView.backgroundColor);
    }
}

#pragma mark - init

- (CAGradientLayer *)bgLayer {
    if (!_bgLayer) {
        _bgLayer = [CAGradientLayer layer];
        int count = 20;
        CGFloat scale = 1.0 / count;
        NSMutableArray *locals = [NSMutableArray array];
        NSMutableArray *colors = [NSMutableArray array];
        for (int index = 0; index < count; index++) {
            [locals addObject:[NSNumber numberWithFloat:scale * (index + 1)]];
            UIColor *color = [UIColor colorWithHue:scale * (index + 1) saturation:1.0 brightness:1.0 alpha:1.0];
            [colors addObject:(id)color.CGColor];
        }
        _bgLayer.locations = locals;
        _bgLayer.colors = colors;
        _bgLayer.startPoint = CGPointMake(0.0, 0.0);
        _bgLayer.endPoint = CGPointMake(0.0, 1.0);
        _bgLayer.frame = self.bounds;
    }
    return _bgLayer;
}

- (CAGradientLayer *)topLayer {
    if (!_topLayer) {
        _topLayer = [CAGradientLayer layer];
        _topLayer.colors = @[(id)[UIColor colorWithWhite:1 alpha:1.0].CGColor,
                             (id)[UIColor colorWithWhite:1 alpha:0.0].CGColor,
                             (id)[UIColor colorWithWhite:1 alpha:0.0].CGColor,
                             (id)[UIColor colorWithWhite:0 alpha:1.0].CGColor];
        _topLayer.locations = @[@0.0, @0.45, @0.6, @1.0];
        _topLayer.startPoint = CGPointMake(0.0, 0.0);
        _topLayer.endPoint = CGPointMake(1.0, 0.0);
        _topLayer.frame = self.bounds;
    }
    return _topLayer;
}

- (UIView *)selBgView {
    if (!_selBgView) {
        _selBgView = [[UIView alloc] initWithFrame:CGRectMake(-15, -15, 30, 30)];
        _selBgView.backgroundColor = [UIColor whiteColor];
        _selBgView.layer.cornerRadius = 15;
        _selBgView.layer.shadowColor = [UIColor colorWithRed:208/255.0 green:208/255.0 blue:208/255.0 alpha:0.1500].CGColor;
        _selBgView.layer.shadowOffset = CGSizeMake(0, 3);
        _selBgView.layer.shadowOpacity = 1;
        _selBgView.layer.shadowRadius = 7;
        [_selBgView addSubview:self.selTopView];
    }
    return _selBgView;
}

- (UIView *)selTopView {
    if (!_selTopView) {
        _selTopView = [[UIView alloc] initWithFrame:CGRectMake(3, 3, 24, 24)];
        _selTopView.backgroundColor = [UIColor whiteColor];
        _selTopView.layer.cornerRadius = 12;
        _selTopView.layer.shadowColor = [UIColor colorWithRed:208/255.0 green:208/255.0 blue:208/255.0 alpha:0.1500].CGColor;
        _selTopView.layer.shadowOffset = CGSizeMake(0, 3);
        _selTopView.layer.shadowOpacity = 1;
        _selTopView.layer.shadowRadius = 7;
    }
    return _selTopView;
}

@end
